#include "include.h"

typedef enum {
   INT,
   LONG,
   UINT,
   STRING,
   LIST
} var_type;


typedef struct {
   var_type type;
   union
   {
      int i;
      long l;
      unsigned int ui;
      char *s;
      list_t *li;
   } data;
} typed_data;

void printList(list_t *l);
int cmp(typed_data*, typed_data*);

int main()
{
   printf("Adding [10-1]\n");
   list_t *l = createList();
   int i;
   for(i=0;i<10;i++)
   {
      typed_data *d = malloc(sizeof(typed_data));
      d->type = INT;
      d->data.i = 10-i;
      addObject(l, d);
   }
   printList(l);
   
   printf("Adding mouse, cat, dog, pigeon, frog, soda\n");
   char *str[] = {
      "mouse",
      "cat",
      "dog",
      "pigeon",
      "frog",
      "soda"
   };
   for(i=0;i<6;i++)
   {
      typed_data *d = malloc(sizeof(typed_data));
      d->type = STRING;
      d->data.s = str[i];
      addObject(l,d);
   }
   printList(l);

   printf("Removing dog\n");
   for(resetList(l);!endList(l);)
   {
      typed_data *d = getObject(l);
      if(d->type == STRING && (strcmp(d->data.s, "dog") == 0))
         removeObject(l, d);
   }
   printList(l);

   printf("Removing dog\n");
   for(resetList(l);!endList(l);)
   {
      typed_data *d = getObject(l);
      if(d->type == STRING && (strcmp(d->data.s, "dog") == 0))
         removeObject(l, d);
   }
   printList(l);

   printf("Removing mouse\n");
   for(resetList(l);!endList(l);)
   {
      typed_data *d = getObject(l);
      if(d->type == STRING && (strcmp(d->data.s, "mouse") == 0))
         removeObject(l, d);
   }
   printList(l);
   
   printf("Removing frog\n");
   for(resetList(l);!endList(l);)
   {
      typed_data *d = getObject(l);
      if(d->type == STRING && (strcmp(d->data.s, "frog") == 0))
         removeObject(l, d);
   }
   printList(l);

   printf("Sorting list\n");
   sortList(l, (int (*)(const void *, const void *))cmp);
   printList(l);
   return 0;
}


/*
 * Prints a list of typed_data only. Let's hope that's enough testing.
 * Oh god this function was stupid to write. I tried doing it with only a few 
 * ternary statements at first but geez did that not work. And as it is it 
 * kinda sucked. Look at that mess. Anyways, glad that's over with. Worst
 * part of this file was writing this silly print function. The actual tests
 * were trivial. And meh. But hey, this list passed Madison's grading so it's
 * probably 100% fine.
 */
void printList(list_t *l)
{
  resetList(l);
  if(!endList(l))
  {
     typed_data *d = getObject(l);
     switch(d->type)
     {
	case INT:
	   printf("( %d", d->data.i);
	   break;
	case LONG:
	   printf("( %ld", d->data.l);
	   break;
	case UINT:
	   printf("( %u", d->data.ui);
	   break;
	case STRING:
	   printf("( \"%s\"", d->data.s);
	   break;
	case LIST:
	   printf("( ");
	   break;
     }
  }
  while(!endList(l))
  {

     typed_data *d = getObject(l);
     switch(d->type)
     {
	case INT:
	   printf(", %d", d->data.i);
	   break;
	case LONG:
	   printf(", %ld", d->data.l);
	   break;
	case UINT:
	   printf(", %u", d->data.ui);
	   break;
	case STRING:
	   printf(", \"%s\"", d->data.s);
	   break;
	case LIST:
	   printf(", ");
	   break;
     }
  }
  printf(" )\n");
}

int cmp(typed_data *a, typed_data *b)
{
   if(a->type != b->type)
      return a->type - b->type;
   if(a->type == INT)
      return a->data.i - b->data.i;
   if(a->type == UINT)
      return a->data.ui - b->data.ui;
   if(a->type == LONG)
      return a->data.l - b->data.l;
   if(a->type == STRING);
      return strcmp(a->data.s, b->data.s);
}
